<?php
/**
 * Created by PhpStorm.
 * User: mac
 * Date: 2021/6/11
 * Time: 9:43 PM
 */

namespace Modules\Auth\Helper;


use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Hash;
use Modules\Common\Entities\Model;
use Modules\Common\Exceptions\BaseException;
use Modules\Common\Exceptions\ServerException;
class GuzzleHttp
{

    private $client;
    private $passportTokenUrl;
    public function __construct() {
        $this->client = new Client();
        $this->passportTokenUrl = config('app.url') . "/" . config("auth.passport.prefix", 'oauth') . '/token';
    }
    /**
     * 获取对应配置
     *
     * @param string $name
     *
     * @return array
     * @author LL
     */
    public function getClientConfig(string $name): array {
        return [
            'client_id'     => intval(config("auth." . $name . "_oauth_client_id")),
            'client_secret' => config("auth." . $name . "_oauth_client_secret"),
        ];
    }
    public function Login(string $username,string $password,array $options = []):array{
        return $this->IsPost(array_merge([
            'grant_type' => 'password',
            'username'   => $username,
            'password'   => $password,
            'scope'      => '*',
        ], $options));
    }
    private  function IsPost($param){
       try {
            $response = $this->client->post(
                $this->passportTokenUrl,
                ['form_params' => $param]);

            $data = $response->getBody()->getContents();
            $data = json_decode($data, true);
            $data['access_token'] = $data['token_type'] . " " . $data['access_token'];
            return $data;
        }catch (ClientException $exception){

            $this->clientException($exception);
        }
    }
    private function clientException($exception){
        if ($exception->getResponse()->getStatusCode() != 401 &&
            $exception->getResponse()->getStatusCode() != 400) {
            throw new ServerException();
        }
        $data = $exception->getResponse()->getBody()->getContents();
        $data = json_decode($data, true);

        switch ($data['error']) {
            case "invalid_grant":
                throw new BaseException('账号密码与客户端不匹配', -1, 401);
            case 'invalid_client':
                throw new BaseException('无效的客户端，请联系管理员', -1, 401);
            case 'invalid_request':
                throw new BaseException('刷新令牌无效', 1, 401);
        }
        throw new ServerException($exception->getMessage());
    }
    /**
     * 销毁指定用户的当前token与 刷新token
     *
     * @param $user
     */
    public function logout($user) {
        $accessToken = $user->token();
        $this->RevokeRefreshTokensByAccessTokenId($accessToken);
    }
    /**
     * 销毁token 与 刷新token
     *
     * @param $token
     */
    public function RevokeRefreshTokensByAccessTokenId($token) {
        $refreshTokenRepository = app('Laravel\Passport\RefreshTokenRepository');
        $refreshTokenRepository->revokeRefreshTokensByAccessTokenId($token->id);
        $token->revoke();
    }
    public function assignrefreshToken(string $refresh_token, string $type){

        $data = $this->getClientConfig($type);
        $client_id = $data['client_id'];
        $client_secret = $data['client_secret'];

        return $this->RefreshToken($refresh_token, $client_id, $client_secret);
    }

    /**
     * 通用刷新token
     *
     * @param        $refresh_token
     * @param        $client_id
     * @param        $client_secret
     * @param string $scope
     *
     * @return mixed
     * @throws BaseException
     * @throws GuzzleException
     * @author LL
     */
    public function RefreshToken($refresh_token, $client_id, $client_secret, $scope = "*") {
        return $this->IsPost([
            'grant_type'    => 'refresh_token',
            'refresh_token' => $refresh_token,
            'client_id'     => $client_id,
            'client_secret' => $client_secret,
            'scope'         => $scope,
        ]);
    }
    /**
     * 重置密码
     *
     * @param model  $user
     * @param string $password
     *
     * @return mixed
     * @author LL
     */
    public function ResetPassword(Model $user, string $password) {
        $user->password = Hash::make($password);
        $user->save();
        $this->tokenAllRevoked($user);
    }
    /**
     * 销毁指定用户的所有token 与刷新token
     *
     * @param $user
     */
    public function tokenAllRevoked($user) {
        $user->tokens->where('revoked', false)->each(function ($token, $key) {
            $this->RevokeRefreshTokensByAccessTokenId($token);
        });
    }
}
